package club.babyf.nativeai.common.handler;

import club.babyf.nativeai.common.exception.BaseException;
import club.babyf.nativeai.common.exception.BusinessException;
import club.babyf.nativeai.common.exception.ErrorCode;
import club.babyf.nativeai.common.exception.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * GlobalExceptionHandler.
 *
 * @author zhanglei.
 * @date 2025/2/21 15:44.
 * @description 全局异常处理.
 */
@Slf4j
@Component
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理validate的校验异常
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<BaseException> paramException(BindException e) {
        log.error(ExceptionUtils.getStackTrace(e));
        List<ObjectError> allErrors = e.getAllErrors();
        String collect = allErrors.parallelStream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        BaseException baseException = new BaseException(collect, ErrorCode.PARAMS_ERROR.getCode());
        return buildResponseEntity(baseException, HttpStatus.OK.value());
    }

    /**
     * 参数错误
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler({HttpMessageConversionException.class, HttpMessageNotReadableException.class, MissingServletRequestParameterException.class, MissingServletRequestPartException.class})
    public ResponseEntity<BaseException> parameterTypeException(Exception e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), ErrorCode.PARAMS_ERROR.getCode()), HttpStatus.OK.value());
    }

    /**
     * 文件上传大小超出限制
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<BaseException> handleFileSizeLimitExceeded(MaxUploadSizeExceededException e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), ErrorCode.PARAMS_ERROR.getCode()), HttpStatus.OK.value());
    }

    /**
     * 业务异常
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler(value = BusinessException.class)
    public ResponseEntity<BaseException> badBusinessException(BusinessException e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), e.getCode()), e.getHttpStatus());
    }

    /**
     * 系统异常
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler(value = SystemException.class)
    public ResponseEntity<BaseException> badSystemException(SystemException e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), e.getCode()), e.getHttpStatus());
    }

    /**
     * 数据库异常
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler({SQLException.class, DataAccessException.class})
    public ResponseEntity<BaseException> badSqlException(SQLException e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), ErrorCode.BUSINESS_ERROR.getCode()), HttpStatus.OK.value());
    }

    /**
     * 未知异常
     *
     * @param e 错误
     * @return 错误提示
     */
    @ExceptionHandler(Throwable.class)
    public ResponseEntity<BaseException> handleException(Throwable e) {
        log.error(ExceptionUtils.getStackTrace(e));
        return buildResponseEntity(new BaseException(e.getMessage(), ErrorCode.SYSTEM_ERROR.getCode()), HttpStatus.OK.value());
    }

    /**
     * 统一返回
     */
    protected ResponseEntity<BaseException> buildResponseEntity(BaseException baseException, int httpStatus) {
        return new ResponseEntity<>(baseException, HttpStatus.valueOf(httpStatus));
    }

}
